package com.business_clean.ui.activity.camera;

import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.DistanceUtil;
import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.NetworkUtils;
import com.blankj.utilcode.util.SizeUtils;
import com.blankj.utilcode.util.TimeUtils;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import com.business_clean.BuildConfig;
import com.business_clean.R;
import com.business_clean.app.App;
import com.business_clean.app.base.BaseActivity;
import com.business_clean.app.config.Constant;
import com.business_clean.app.ext.CommonUtils;
import com.business_clean.app.network.NetUrl;
import com.business_clean.app.service.LocService;
import com.business_clean.app.service.ServerReporter;
import com.business_clean.app.uitl.ActivityForwardUtil;
import com.business_clean.app.uitl.ImageCompressor;
import com.business_clean.app.uitl.Mp4Utils;
import com.business_clean.app.uitl.PhotoBitmapUtils;
import com.business_clean.app.uitl.ResultDouble;
import com.business_clean.app.uitl.RxHelper;
import com.business_clean.app.uitl.ToastUtil;
import com.business_clean.app.weight.camera.CaptureButton;
import com.business_clean.app.weight.camera.CaptureListener;
import com.business_clean.app.weight.dialog.CameraSettingDialog;
import com.business_clean.app.weight.dialog.CustomClockInDialog;
import com.business_clean.app.weight.dialog.PagerDrawerPopup;
import com.business_clean.data.initconfig.TimestampEntity;
import com.business_clean.data.initconfig.WaterMarkBitmapData;
import com.business_clean.data.mode.address.AddressEntity;
import com.business_clean.data.mode.address.AddressListEntity;
import com.business_clean.data.mode.project.CheckClockInEntity;
import com.business_clean.data.mode.project.ProjectMangerList;
import com.business_clean.databinding.ActivityCameraBinding;
import com.business_clean.ui.activity.me.MyCenterActivity;
import com.business_clean.ui.adapter.watermark.WaterClockAdapter;
import com.business_clean.viewmodel.request.CameraViewModel;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.luck.picture.lib.interfaces.OnKeyValueResultCallbackListener;
import com.lxj.xpopup.XPopup;
import com.otaliastudios.cameraview.CameraException;
import com.otaliastudios.cameraview.CameraListener;
import com.otaliastudios.cameraview.CameraOptions;
import com.otaliastudios.cameraview.PictureResult;
import com.otaliastudios.cameraview.VideoResult;
import com.otaliastudios.cameraview.controls.Audio;
import com.otaliastudios.cameraview.controls.Facing;
import com.otaliastudios.cameraview.controls.Flash;
import com.otaliastudios.cameraview.controls.PictureFormat;
import com.otaliastudios.cameraview.gesture.Gesture;
import com.otaliastudios.cameraview.gesture.GestureAction;
import com.otaliastudios.cameraview.gesture.TapGestureFinder;
import com.otaliastudios.cameraview.size.Size;

import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableSource;
import io.reactivex.rxjava3.core.Scheduler;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;
import me.hgj.mvvmhelper.ext.AppExtKt;
import me.hgj.mvvmhelper.ext.LogExtKt;
import rxhttp.wrapper.param.RxHttp;


import static java.lang.Math.abs;
import static me.hgj.mvvmhelper.ext.CommExtKt.isLocationOpen;

/**
 * 水印相机操作界面
 * 1、地址定位
 * 2、请求权限
 * 3、服务器时间校准
 */
public class WatermarkCameraActivity extends BaseActivity<CameraViewModel, ActivityCameraBinding> {


    private String TAG = "WatermarkCameraActivity";

    //旋转的角度
    private final int ORIGIN = 0;
    private final int LEFT = 1;
    private final int RIGHT = 2;
    private final int TOP = 3;
    //录制视频的最大时常
    private final int MAX_VIDEO_TIME = 1000 * 60 * 30;


    private boolean showFocuseView = true;

    private Size pictureSize;

    //来控制闪光灯 默认关闭
    private int isFlash = 0;

    private AnimatorSet setScale;

    //录制倒计时
    private Disposable time;
    //时间校准
    private Disposable disposableTimer;

    public List<String> mp4List = new ArrayList<>();

    private View securityView = null;

    private Disposable disposablePhoto;

    //百度地图的api
    private LocService locService;

    private long takePhotoMills = 0;
    private double currentLatitude = 0.0;
    private double currentLongitude = 0.0;
    private String currentAddress = "无定位地址";

    private CaptureButton captureButton;

    private boolean isRecordShort = true;//记录是否是录制时间过短

    private TextView tvSecurityView = null;

    private boolean isActionVideo = false; //检查操作是视频还是拍照

    private WaterClockAdapter mAdapter;//标记打卡的内容

    @Override
    public void initView(@Nullable Bundle savedInstanceState) {
        //设置录制按钮的
        captureButton = new CaptureButton(this);
        FrameLayout.LayoutParams btn_capture_param = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        btn_capture_param.gravity = Gravity.CENTER;
        captureButton.setLayoutParams(btn_capture_param);
        mDatabind.flCapture.addView(captureButton);
        //防伪码相关的内容
        securityView = getLayoutInflater().inflate(R.layout.view_water_mask_security, null);
        tvSecurityView = securityView.findViewById(R.id.tv_mash_security);

        //设置项目
        mDatabind.tvProject.setText(App.appViewModelInstance.getProjectInfo().getValue().getProject_short_name());

        if (Constant.ROLE_CLEANER) {//如果是保洁员 就显示个拍照按钮
            mDatabind.llCameraTodo.setVisibility(View.INVISIBLE);
            mDatabind.llCameraWork.setVisibility(View.INVISIBLE);
            mDatabind.llCameraRoster.setVisibility(View.INVISIBLE);
            mDatabind.llCameraCircle.setVisibility(View.INVISIBLE);
            mDatabind.ivProject.setVisibility(View.GONE);
        }
        XXPermissions.with(this).permission(Permission.CAMERA, Permission.ACCESS_FINE_LOCATION,
                        Permission.MANAGE_EXTERNAL_STORAGE, Permission.RECORD_AUDIO)
                .request(new OnPermissionCallback() {
                    @Override
                    public void onGranted(@NonNull List<String> permissions, boolean allGranted) {
                        if (allGranted) {
                            initCamera();
                            createTimer();
                            mDatabind.viewWaterMask.getTvAddress().setText(currentAddress);
                            mDatabind.viewWaterMask1.getTvAddress().setText(currentAddress);
                            getCurrentLocation();
                            requestNetDate();
                        } else {
                            ToastUtil.show("使用该功能，需要使用到特定权限，请开启后再使用");
                        }
                    }
                });
        //打卡类型
        List<String> arr = new ArrayList<>();
        if (Constant.ROLE_PROJECT_OWNER || Constant.ROLE_LEADER || Constant.ROLE_CLEANER) {
            arr.add("打卡");
        }
        if (!Constant.ROLE_CLEANER) {
            arr.add("领班打卡");
        }
        if (!Constant.ROLE_CLEANER) {
            arr.add("日常");
        }
        mAdapter = new WaterClockAdapter();
        mAdapter.setList(arr);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        mDatabind.recycler.setLayoutManager(layoutManager);
        mDatabind.recycler.setAdapter(mAdapter);
        mAdapter.updateSingleItem(arr.get(0));//默认选中第一个
    }


    private void createTimer() {
        disposableTimer = Observable.interval(1, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(aLong -> {
            requestNetDate();
        });
    }

    private void initCamera() {
        mDatabind.cameraView.setLifecycleOwner(this);
        mDatabind.cameraView.setPictureFormat(PictureFormat.JPEG);
        mDatabind.cameraView.setPictureSize(source -> {
            Size size = findSize(source);
            this.pictureSize = size;
            return Collections.singletonList(size);
        });

        mDatabind.cameraView.setPreviewStreamSize(source -> Collections.singletonList(findSize(source)));
        mDatabind.cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM); // Pinch to zoom!
        mDatabind.cameraView.mapGesture(Gesture.TAP, GestureAction.AUTO_FOCUS); // Tap to focus!
        mDatabind.cameraView.mapGesture(Gesture.LONG_TAP, GestureAction.AUTO_FOCUS); // Tap to focus!
        mDatabind.cameraView.setAutoFocusResetDelay(3000);
//        mDatabind.cameraView.setAutoFocusMarker(new RDautoFocusMarker());
        mDatabind.cameraView.addCameraListener(new CameraListener() {
            @Override
            public void onCameraOpened(@NonNull CameraOptions options) {
                super.onCameraOpened(options);
                LogUtils.e("onCameraOpened");
                toggleCamera(true);
                if (mDatabind.cameraView.getFacing() == Facing.FRONT) {
//                    mDatabind.ivFlash.setVisibility(View.GONE);
                } else {
                    if (mDatabind.cameraView.isTakingVideo()) {
                        return;
                    }
//                    mDatabind.ivFlash.setVisibility(!options.getSupportedFlash().isEmpty() ? View.VISIBLE : View.GONE);
                }
            }

            @Override
            public void onOrientationChanged(int orientation) {
                super.onOrientationChanged(orientation);
                LogExtKt.logE("onOrientationChanged--》" + orientation, TAG);
                //正在拍摄视频过程中不允许旋转
                if (mDatabind.cameraView.isTakingVideo()) {
                    return;
                }
                switch (orientation) {
                    case 0:
                    case 180:
                        rotateText(ORIGIN);
                        break;
                    case 90:
                        rotateText(ORIGIN);
//                        rotateText(RIGHT);// 90 这是以前的写法
                        break;
                    case 270:
                        rotateText(LEFT);
                        break;
                }
                //只检测是否有四个角度的改变
            }

            @Override
            public void onCameraClosed() {
                super.onCameraClosed();
                toggleCamera(false);
            }

            @Override
            public void onCameraError(@NonNull CameraException exception) {
                super.onCameraError(exception);
                toggleCamera(false);
                LogUtils.e(exception);
            }

            @Override
            public void onPictureShutter() {
                super.onPictureShutter();
                LogExtKt.logE("onPictureShutter", TAG);
            }

            @Override
            public void onPictureTaken(@NonNull PictureResult result) {
                super.onPictureTaken(result);
                LogExtKt.logE("onPictureTaken", TAG);
                takePhotoMills = System.currentTimeMillis();//拿到拍照当前的时间戳
                //设置防伪码
                if (tvSecurityView != null) {
                    tvSecurityView.setText("防伪码 " + takePhotoMills);
                }
                if (!Constant.ROLE_CLEANER && !mAdapter.getText().equals("打卡")) {
                    JumpEditPhoto(true, compositeBitmap(result.getData(), result.getRotation(), result.getFacing()), ImageUtils.view2Bitmap(mDatabind.viewWaterMask), ImageUtils.view2Bitmap(securityView), null);
                } else {
                    //拍完照片了，进行合成
                    disposablePhoto = Observable.just(result.getData()).flatMap((Function<byte[], ObservableSource<ResultDouble<Bitmap, Bitmap>>>) bytes -> {
                        //byte合成bitmap
                        Bitmap originalBitmap = compositeBitmap(result.getData(), result.getRotation(), result.getFacing());
                        //缓存 提高绘图速度
                        mDatabind.viewWaterMask.setDrawingCacheEnabled(true);

                        //合成水印照片
                        Bitmap waterMarkBitmap = PhotoBitmapUtils.drawWaterToBitMap2(WatermarkCameraActivity.this,
                                mDatabind.viewWaterMask.getDrawingCache(), originalBitmap, ImageUtils.view2Bitmap(securityView));

                        //清除水印的缓存
                        mDatabind.viewWaterMask.destroyDrawingCache();

//                        String finalFileName = System.currentTimeMillis() + ".jpg";
//                        File file = null;
//                        File originalFile = null;
//                        String savePath = Constant.CAMERA_SAVE_PHOTO_VIDEO ? Constant.EXTERNAL_PHOTO_PATH : Constant.INTERNAL_PHOTO_PATH;
//
//                        if (!Constant.CAMERA_SAVE_PHOTO_VIDEO) {
//                            file = saveBitmapToFile(waterMarkBitmap, savePath, finalFileName);
//                            originalFile = saveBitmapToFile(originalBitmap, savePath, finalFileName + "_1");
//                        } else {
//                            file = ImageUtils.save2Album(waterMarkBitmap, savePath, Bitmap.CompressFormat.JPEG);
//                            originalFile = Constant.CAMERA_SAVE_ORIGINAL_PHOTO ? ImageUtils.save2Album(originalBitmap, savePath, Bitmap.CompressFormat.JPEG) : saveBitmapToFile(originalBitmap, savePath, finalFileName + "_1");
//                        }
//
//                        File finalFile = file;
//                        File finalOriginalFile = originalFile;
                        return observer -> observer.onNext(new ResultDouble<>(waterMarkBitmap, originalBitmap));

                    }).compose(RxHelper.rxSchedulerHelper()).subscribe(bitmapResultSingle -> {
//                        if (file != null && file.returnValue3 != null) {
//                            animation(file.returnValue3);
//                            String waterFilePath = file.returnValue2.getAbsolutePath();
//                            String originalFilePath = file.returnValue4.getAbsolutePath();
//                            uploadMedia(1, waterFilePath, originalFilePath);//上报给后段
//                        }
                        // value 1 是水印图 value2 是原图
                        if (bitmapResultSingle.returnValue1 != null && bitmapResultSingle.returnValue2 != null) {
//                            animation(bitmapResultSingle.returnValue1);
                            handlerWaterUpload(bitmapResultSingle.returnValue1, bitmapResultSingle.returnValue2);
                        }
                    });
                }
            }

            /**
             * 收入相册动画
             * @param bitmap
             */
            public void animation(Bitmap bitmap) {
                mDatabind.preImgLinear.setVisibility(View.VISIBLE);
                if (!isDestroyed()) {
                    Glide.with(mDatabind.preImg.getContext()).load(bitmap).apply(RequestOptions.bitmapTransform(new RoundedCorners(SizeUtils.dp2px(8)))).into(mDatabind.preImg);
                }
                ObjectAnimator animatorScaleX = ObjectAnimator.ofFloat(mDatabind.preImg, "scaleX", 1f, 1f, 1f, 0f);
                ObjectAnimator animatorScaleY = ObjectAnimator.ofFloat(mDatabind.preImg, "scaleY", 1f, 1f, 1f, 0f);

                int[] location = new int[2];

                mDatabind.llCameraCircle.getLocationInWindow(location);
                mDatabind.preImg.setPivotX(location[0] - mDatabind.llCameraCircle.getWidth() / 2);
                mDatabind.preImg.setPivotY(location[1] - mDatabind.llCameraCircle.getHeight() * 2);

                setScale = new AnimatorSet();
                setScale.playTogether(animatorScaleX, animatorScaleY);
                setScale.setDuration(1000);
                setScale.start();
                setScale.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mDatabind.preImgLinear.setVisibility(View.GONE);
                    }
                });
            }

            @Override
            public void onAutoFocusStart(@NonNull PointF point) {
                super.onAutoFocusStart(point);
                LogExtKt.logE("onAutoFocusStart", TAG);
                //651.0, 938.0
                mDatabind.cfvView.setTranslationX(point.x - SizeUtils.dp2px(40));
                mDatabind.cfvView.setTranslationY(point.y - SizeUtils.dp2px(40));
                mDatabind.cfvView.setVisibility(View.VISIBLE);
                mDatabind.cfvView.setIslongClick(isLongClick());
                if (showFocuseView) {
                    mDatabind.cfvView.setVisibility(View.VISIBLE);
                } else {
                    mDatabind.cfvView.setVisibility(View.GONE);
                }

            }

            @Override
            public void onAutoFocusEnd(boolean successful, @NonNull PointF point) {
                super.onAutoFocusEnd(successful, point);
                LogExtKt.logE("onAutoFocusEnd", TAG);

                if (isLongClick() && showFocuseView) {
//                    mDatabind.cameraView.startAutoFocus(point.x, point.y);
                    LogExtKt.logE("onAutoFocusEnd", TAG);
                } else {
                    mDatabind.cfvView.animate().setDuration(300).setStartDelay(1000).setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            super.onAnimationEnd(animation);
                            mDatabind.cfvView.setVisibility(View.GONE);

                        }
                    }).start();
                }

            }

            @Override
            public void onVideoRecordingStart() {
                super.onVideoRecordingStart();
                LogExtKt.logE("onVideoRecordingStart", TAG);
            }

            @Override
            public void onVideoRecordingEnd() {
                super.onVideoRecordingEnd();
                LogExtKt.logE("onVideoRecordingEnd", TAG);
            }

            @Override
            public void onVideoTaken(@NonNull VideoResult result) {
                super.onVideoTaken(result);
                //视频录制完成
                LogExtKt.logE("onVideoTaken-->" + result.getFile().getAbsoluteFile(), TAG);
                LogExtKt.logE("onVideoTaken-->" + isRecordShort, TAG);
                if (!isRecordShort) {
                    takePhotoMills = System.currentTimeMillis();//拿到拍照当前的时间戳
                    if (!Constant.ROLE_CLEANER && !mAdapter.getText().equals("打卡")) {
                        JumpEditPhoto(false, null, null, null, result.getFile().getAbsolutePath());
                    } else {
                        mp4List.add(result.getFile().getAbsolutePath());
                        mergeMp4List();
                    }
                }
            }

            @Override
            public void onZoomChanged(float newValue, @NonNull float[] bounds, @androidx.annotation.Nullable PointF[] fingers) {
                super.onZoomChanged(newValue, bounds, fingers);
                LogExtKt.logE("onZoomChanged-->", TAG);

            }
        });
    }

    /**
     * 上报压缩图片到服务器
     *
     * @param waterMarkBitmap
     * @param originalBitmap
     */
    private void handlerWaterUpload(Bitmap waterMarkBitmap, Bitmap originalBitmap) {
        //在这里对水印图片进行压缩 并且上报
        //先存到本地项目
        File file = saveBitmapToFile(waterMarkBitmap, Constant.INTERNAL_PHOTO_PATH, System.currentTimeMillis() + ".jpg");//水印拿到一个暂存的路径
        File originaFile = saveBitmapToFile(originalBitmap, Constant.INTERNAL_PHOTO_PATH, System.currentTimeMillis() + "origina" + ".jpg");//原图拿到一个暂存的路径
        File thumbFile = saveBitmapToFile(PhotoBitmapUtils.getBitmapThumb(file.getAbsolutePath(), 200), Constant.INTERNAL_PHOTO_PATH, System.currentTimeMillis() + "thumb" + ".jpg");
        //先压缩水印图片
        ImageCompressor.compressBitmap(this, file.getAbsolutePath(), 10, new OnKeyValueResultCallbackListener() {
            @Override
            public void onCallback(String srcPath, String resultWaterPath) {
                //原图的压缩 压缩完成后 再去上传服务器，因为服务器要原图跟水印图，所以都需要压缩后 处理
                ImageCompressor.compressBitmap(WatermarkCameraActivity.this,
                        originaFile.getAbsolutePath(), 10, new OnKeyValueResultCallbackListener() {
                            @Override
                            public void onCallback(String srcPath, String resultPath) {
                                LogUtils.e("压缩完成后的图片 resultPath -->" + resultPath);
                                ImageCompressor.compressBitmap(WatermarkCameraActivity.this,
                                        thumbFile.getAbsolutePath(), 10, new OnKeyValueResultCallbackListener() {
                                            @Override
                                            public void onCallback(String srcPath, String thumbPath) {
                                                LogUtils.e("压缩完成后的图片 resultPath -->" + thumbPath);
                                                //拿到压缩后的路径了，那么就进行存储
                                                if (Constant.CAMERA_SAVE_PHOTO_VIDEO) {//开启本地照片存储 需要保存水印照片
                                                    ImageUtils.save2Album(BitmapFactory.decodeFile(resultWaterPath), Constant.EXTERNAL_PHOTO_PATH, Bitmap.CompressFormat.JPEG);
                                                    //是否需要保存原始图片到相册
                                                    if (Constant.CAMERA_SAVE_ORIGINAL_PHOTO) {
                                                        ImageUtils.save2Album(BitmapFactory.decodeFile(resultPath), Bitmap.CompressFormat.JPEG);
                                                    }
                                                }
                                                uploadMedia(1, resultWaterPath, resultPath, thumbPath);
                                            }
                                        });
                            }
                        });

            }
        });
    }

    /**
     * 跳转处理
     *
     * @param isPic
     * @param compositeBitmap
     * @param view2Bitmap
     * @param view2Bitmap1
     * @param video_path
     */
    private void JumpEditPhoto(boolean isPic, Bitmap compositeBitmap, Bitmap view2Bitmap, Bitmap view2Bitmap1, String video_path) {
        WaterMarkBitmapData markBitmapData = new WaterMarkBitmapData();
        //设置原图
        markBitmapData.setOriginalBitmap(compositeBitmap);
        //设置水印图
        markBitmapData.setWaterBitmap(view2Bitmap);
        //设置防伪码的图
        markBitmapData.setKeyBitmap(view2Bitmap1);
        //经纬度 地址
        markBitmapData.setLat(currentLatitude);
        markBitmapData.setLnt(currentLongitude);
        markBitmapData.setAddress(currentAddress);
        //给共同的数据，因为通过bundle 怕图片过大
        App.appViewModelInstance.getWaterMarkBitmap().setValue(markBitmapData);
        Bundle bundle = new Bundle();
        bundle.putInt("channel", isPic ? 1 : 2);
        bundle.putString("takePhotoMills", "" + takePhotoMills);
        bundle.putString("video_path", video_path);
        bundle.putString("act_type", mAdapter.getText());
        ActivityForwardUtil.startActivity(EditPhotoActivity.class, bundle);
    }

    private File saveBitmapToFile(Bitmap waterMarkBitmap, String savePath, String finalFileName) {
        File file = new File(savePath + finalFileName);
        ImageUtils.save(waterMarkBitmap, savePath + finalFileName, Bitmap.CompressFormat.JPEG);
        return file;
    }

    @Override
    public void initObserver() {
        mDatabind.viewWaterMask.getTvAddress().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //判断下是否开启定位权限 如果没开启，就提示开启
                if (!XXPermissions.isGranted(WatermarkCameraActivity.this, Permission.ACCESS_FINE_LOCATION)) {
                    XXPermissions.with(WatermarkCameraActivity.this)
                            .permission(Permission.ACCESS_FINE_LOCATION)
                            .request(new OnPermissionCallback() {
                                @Override
                                public void onGranted(@NonNull List<String> permissions, boolean allGranted) {
                                    if (allGranted) {
                                        getCurrentLocation();
                                    }
                                }
                            });
                }
            }
        });


        //监听是否切换项目
        App.appViewModelInstance.getProjectInfo().observe(this, new Observer<ProjectMangerList>() {
            @Override
            public void onChanged(ProjectMangerList projectMangerList) {
                mDatabind.tvProject.setText(projectMangerList.getProject_short_name());
            }
        });
    }


    private void getCurrentLocation() {
        locService = new LocService(this);
        locService.registerListener(mListener);
        locService.setLocationOption(locService.getDefaultLocationClientOption());
        locService.start();
        logText("有权限了，来进行百度地图定位了版本 - " + locService.getSDKVersion());
    }

    @Override
    public void onBindViewClick() {
        closeCamera(mDatabind.llCameraWork, 0);
        closeCamera(mDatabind.llCameraTodo, 1);
        closeCamera(mDatabind.llCameraCircle, 3);
        closeCamera(mDatabind.llCameraRoster, 4);
        //打卡方式
        mAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
                mAdapter.updateSingleItem(mAdapter.getData().get(position));
            }
        });
        //切换项目
        mDatabind.llChangeProject.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Constant.ROLE_CLEANER) {
                    return;
                }
                new XPopup.Builder(WatermarkCameraActivity.this)
                        .asCustom(new PagerDrawerPopup(WatermarkCameraActivity.this)).show();
            }
        });

        //按钮的长按
        captureButton.setCaptureLisenter(new CaptureListener() {
            @Override
            public void onTick(long time) {
                LogUtils.e("" + time);
            }

            @Override
            public void takePictures() {
                isActionVideo = false;
                if (currentLatitude == 0.0 || currentLongitude == 0.0) {
                    CommonUtils.showGeneralDialogNoCancel(WatermarkCameraActivity.this, "温馨提示", "没有获取到定位地址，无法打卡", "知道了", null);
                    return;
                }
                Observable.fromCallable(() -> {
                            // 在这里执行网络请求操作，比如检查网络是否可用
                            return NetworkUtils.isAvailable();
                        })
                        .subscribeOn(Schedulers.io())  // 在 IO 线程执行网络请求
                        .observeOn(AndroidSchedulers.mainThread())  // 在主线程处理结果
                        .subscribe(isNetworkAvailable -> {
                            if (!isNetworkAvailable) {
                                ToastUtil.show("请联网后再打卡");
                                CommonUtils.showGeneralDialogNoCancel(WatermarkCameraActivity.this, "温馨提示", "请联网后再打卡", "知道了", null);
                            } else {
                                // 继续执行其他操作，如发起打卡请求
                                mDatabind.cameraView.takePicture();
                            }
                        });
            }

            @Override
            public void recordShort(long l) {
                isRecordShort = true;
                ToastUtil.show("录制时间过短");
                mDatabind.cameraView.stopVideo();
                switchVideoMode(true);
                mDatabind.clTime.setVisibility(View.GONE);
                if (time != null) {
                    time.dispose();
                }
            }

            @Override
            public void recordStart() {
                isActionVideo = false;
                if (currentLongitude == 0.0 || currentLatitude == 0.0) {
                    CommonUtils.showGeneralDialogNoCancel(WatermarkCameraActivity.this, "温馨提示", "没有获取到定位地址，无法打卡", "知道了", null);
                    captureButton.recordEnd();
                    return;
                }
                starTakeVideo();
            }

            @Override
            public void recordEnd(long l) {
                isRecordShort = false;
                if (mDatabind.cameraView.isTakingVideo()) {
                    mDatabind.cameraView.stopVideo();
                    switchVideoMode(true);
                    mDatabind.clTime.setVisibility(View.GONE);
                    if (time != null) {
                        time.dispose();
                    }
                    ToastUtil.show("视频录制完成");
                }
            }

            @Override
            public void recordZoom(float zoom) {

            }

            @Override
            public void recordError() {
                if (time != null) {
                    time.dispose();
                }
            }
        });

        //相机的设置
        mDatabind.ivSetting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new XPopup.Builder(WatermarkCameraActivity.this)
                        .asCustom(new CameraSettingDialog(WatermarkCameraActivity.this, isFlash, new CameraSettingDialog.CameraSettingDialogListener() {
                            @Override
                            public void clickChange(int how) {
                                switch (how) {
                                    case 1://闪光灯
                                        if (isFlash == 0) {
                                            isFlash = 1;
                                            mDatabind.cameraView.setFlash(Flash.TORCH);
//                                            mDatabind.ivFlash.setImageResource(R.mipmap.icon_camera_flash_open);
                                        } else if (isFlash == 1) {
                                            isFlash = 2;
                                            mDatabind.cameraView.setFlash(Flash.AUTO);
//                                            mDatabind.ivFlash.setImageResource(R.mipmap.icon_camera_auto_flash);
                                        } else {
                                            isFlash = 0;
                                            mDatabind.cameraView.setFlash(Flash.OFF);
//                                            mDatabind.ivFlash.setImageResource(R.mipmap.icon_camera_flash);
                                        }
                                        break;
                                    case 2://切换镜头
                                        mDatabind.cameraView.toggleFacing();
                                        break;
                                    case 3://相机设置
                                        ActivityUtils.startActivity(CameraSettingActivity.class);
                                        break;
                                    case 4://个人中心
                                        ActivityUtils.startActivity(MyCenterActivity.class);
                                        break;
                                }
                            }
                        })).show();
            }
        });


    }


    /**
     * 启动相机
     */
    private void starTakeVideo() {
        switchVideoMode(false);
        mDatabind.tvMashSecurity.setText("防伪码:" + TimeUtils.getNowMills());
        mDatabind.clTime.setVisibility(View.VISIBLE);
        mDatabind.tvTime.setText("0:00");
        mDatabind.cameraView.setAudio(Audio.ON);
        File file = new File(getCacheDir(), System.currentTimeMillis() + ".mp4");
        mDatabind.cameraView.takeVideoSnapshot(file, MAX_VIDEO_TIME);
        if (time != null) {
            time.dispose();
        }
        time = Observable.interval(0, 1, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long seconds) throws Exception {
                mDatabind.tvTime.setText(formatTime(seconds));
            }
        });
    }


    public boolean isLongClick() {
        try {
            for (Field field : mDatabind.cameraView.getClass().getDeclaredFields()) {
                if (field.getType() == TapGestureFinder.class) {
                    field.setAccessible(true);
                    TapGestureFinder tapGestureFinder = (TapGestureFinder) field.get(mDatabind.cameraView);
                    return tapGestureFinder.getGesture() == Gesture.LONG_TAP;
                }
            }
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 这里是完成图片
     */
    private Bitmap compositeBitmap(byte[] bytes, int rotation, Facing facing) {
        //byte合成bitmap
        Bitmap originalBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        //旋转图片的角度
        originalBitmap = PhotoBitmapUtils.rotateBitmap(originalBitmap, rotation, true);
        //如果是前置摄像头拍的,把图片翻转正确
        if (facing == Facing.FRONT) {
            originalBitmap = PhotoBitmapUtils.convertBmp(originalBitmap, true);
        }
        return originalBitmap;
    }

    /**
     * 旋转当前屏幕上的文字
     *
     * @param orientation
     */
    private void rotateText(int orientation) {
        ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT);

        switch (orientation) {
            case ORIGIN://下
                mDatabind.llChangeProject.setVisibility(View.VISIBLE);
                mDatabind.llChangeProject.setRotation(0);
                mDatabind.viewWaterMask.setRotation(0);
                layoutParams.startToStart = ConstraintSet.PARENT_ID;
                layoutParams.bottomToTop = mDatabind.llBottom.getId();
//                layoutParams.leftMargin = SizeUtils.dp2px(15);
//                layoutParams.bottomMargin = SizeUtils.dp2px(15);
                layoutParams.goneBottomMargin = SizeUtils.dp2px(90);
                mDatabind.viewWaterMask.setLayoutParams(layoutParams);
                break;
            case RIGHT://右
                mDatabind.viewWaterMask.setPivotX(mDatabind.viewWaterMask.getWidth() - SizeUtils.dp2px(50));
                mDatabind.viewWaterMask.setPivotY(-SizeUtils.dp2px(80));
                layoutParams.bottomToTop = mDatabind.llBottom.getId();
//                layoutParams.startToStart = ConstraintSet.PARENT_ID;
//                layoutParams.rightMargin = mDatabind.viewWaterMask.getHeight() + SizeUtils.dp2px(15);
                mDatabind.viewWaterMask.setRotation(-90);
                mDatabind.viewWaterMask.setLayoutParams(layoutParams);
                break;
            case LEFT://左
                mDatabind.viewWaterMask.setPivotX(0);
                mDatabind.viewWaterMask.setPivotY(0);
                layoutParams.width = mDatabind.cameraView.getHeight();
                layoutParams.startToStart = ConstraintSet.PARENT_ID;
                layoutParams.leftMargin = mDatabind.viewWaterMask.getHeight();
                layoutParams.topMargin = 0;
                mDatabind.viewWaterMask.setRotation(90);
                mDatabind.viewWaterMask.setLayoutParams(layoutParams);
                mDatabind.llChangeProject.setVisibility(View.GONE);
                break;
            //暂时砍掉  不需要做这个
            case TOP://上
                mDatabind.viewWaterMask.setRotation(180);
                layoutParams.bottomToTop = mDatabind.llBottom.getId();
                layoutParams.endToEnd = ConstraintSet.PARENT_ID;
                layoutParams.rightMargin = SizeUtils.dp2px(15);
                layoutParams.bottomMargin = SizeUtils.dp2px(15);
                layoutParams.topMargin = mDatabind.viewWaterMask.getWidth() / 3 + 15;
                mDatabind.viewWaterMask.setLayoutParams(layoutParams);
                break;
        }
    }


    /**
     * 合并Mp4
     */
    public void mergeMp4List() {
        String savePath = Constant.CAMERA_SAVE_PHOTO_VIDEO ? Constant.EXTERNAL_PHOTO_PATH : Constant.INTERNAL_VIDEO_PATH;
        Mp4Utils.mergeMp4List(mp4List, new File(savePath + "/" + System.currentTimeMillis() + "mergeVideo.mp4"))
                .compose(RxHelper.rxSchedulerHelper()).subscribe(new Consumer<File>() {
                    @Override
                    public void accept(File mergeVideo) throws Exception {
                        if (Constant.CAMERA_SAVE_PHOTO_VIDEO) {
                            Mp4Utils.saveVideoToAlbum(WatermarkCameraActivity.this, mergeVideo.getAbsolutePath());
                            FileUtils.notifySystemToScan(mergeVideo);
                        }
                        mp4List.clear();
                        LogExtKt.logE("合并了完成了 " + mergeVideo.getAbsolutePath(), TAG);
                        //上传视频
                        Bitmap thumb = PhotoBitmapUtils.getVideoThumbnail(mergeVideo.getAbsolutePath(), 90, 160, MediaStore.Video.Thumbnails.MINI_KIND);
                        File thumbFile = saveBitmapToFile(thumb, Constant.INTERNAL_PHOTO_PATH, System.currentTimeMillis() + "video_thumb" + ".jpg");
                        //先压缩缩略图，拿到缩略图的大小
                        ImageCompressor.compressBitmap(WatermarkCameraActivity.this,
                                thumbFile.getAbsolutePath(), 10, new OnKeyValueResultCallbackListener() {
                                    @Override
                                    public void onCallback(String srcPath, String thumbPath) {
                                        LogUtils.e("压缩完成后的图片 resultPath -->" + thumbPath);
                                        uploadMedia(2, mergeVideo.getAbsolutePath(), null, thumbPath);
                                    }
                                });
                    }
                }, throwable -> {
                    throwable.printStackTrace();
                    LogExtKt.logE("合并出现异常" + throwable.getMessage(), TAG);
                    switchVideoMode(false);
                });
    }

    private void switchVideoMode(boolean b) {
        mDatabind.ivSetting.setVisibility(b ? View.VISIBLE : View.GONE);
//        mDatabind.ivChange.setVisibility(b ? View.VISIBLE : View.GONE);
//        mDatabind.ivFlash.setVisibility(b ? View.VISIBLE : View.GONE);
    }

    @Override
    protected void onRestart() {
        super.onRestart();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onStop() {
        if (locService != null) {
            locService.unregisterListener(mListener); //注销掉监听
            locService.stop();
        }
        super.onStop();
    }

    @Override
    protected void onPause() {
        super.onPause();
//        mDatabind.ivFlash.setVisibility(View.VISIBLE);
//        mDatabind.ivChange.setVisibility(View.VISIBLE);
        mDatabind.ivSetting.setVisibility(View.VISIBLE);
        showFocuseView = false;
        mDatabind.cfvView.setVisibility(View.GONE);
        if (mDatabind.cameraView.isTakingVideo()) {
            mDatabind.cameraView.stopVideo();
        }
    }

    private void toggleCamera(boolean isOpen) {
        if (captureButton != null) {
            captureButton.setEnabled(isOpen);
        }
//        mDatabind.butCircleProgress.setEnabled(isOpen);
    }


    public String formatTime(long time) {
        long minutes = TimeUnit.SECONDS.toMinutes(time) % 60;
        if (time >= 60 * 60) {
            minutes = 60;
        }
        long seconds = time % 60;
        return String.format("%d:%02d", minutes, seconds);

    }


    /**
     * 计算值
     *
     * @param source
     * @return
     */
    private Size findSize(List<Size> source) {
//        double targetRatio = (double) 3 / 4;//预览标准比值
        double targetRatio = (double) 9 / 16;//预览标准比值
        double aspectTolerance = 0.1;//预览标准比值
        double minDiff = Double.MAX_VALUE;
//        int targetHeight = 1440;
//        int targetWidth = 1080;
        int targetHeight = 1920; // 对应16:9宽高比
        int targetWidth = 1080; // 对应16:9宽高比
        Size optimalSize = null;

        // Try to find an size match aspect ratio and size
        for (Size size : source) {
            double ratio = size.getWidth() / (float) size.getHeight();
            if (abs(ratio - targetRatio) > aspectTolerance) {
                continue;
            }
            int diff = abs(size.getWidth() - targetWidth) + abs(size.getHeight() - targetHeight);
            if (diff < minDiff) {
                optimalSize = size;
                minDiff = diff;
            }
        }
        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : source) {
                int diff = abs(size.getHeight() - targetHeight) + abs(size.getWidth() - targetWidth);
                if (diff < minDiff) {
                    optimalSize = size;
                    minDiff = diff;
                }
            }
        }
        LogUtils.e("实际计算尺寸" + optimalSize);
        return optimalSize;
    }

    /**
     * 关闭当前界面，跳转到首页的内容
     */
    private void closeCamera(View mView, int position) {
        mView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (time != null) {
                    time.dispose();
                }
                if (disposableTimer != null) {
                    disposableTimer.dispose();
                }
                if (disposablePhoto != null) {
                    disposablePhoto.dispose();
                }
                AppExtKt.finishActivity(WatermarkCameraActivity.class);
                overridePendingTransition(0, 0);
                App.appViewModelInstance.getBackPosition().setValue(position);
            }
        });

    }

    /**
     * 请求网络 校准地址
     */
    private void requestNetDate() {
        RxHttp.get(NetUrl.GET_TIME_STAMP)
                .asResponse(TimestampEntity.class)
                .timeout(3, TimeUnit.SECONDS)  //设置总超时时间为5s，在toObservableXxx方法后调用
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<TimestampEntity>() {
                    @Override
                    public void accept(TimestampEntity response) throws Exception {
                        Long time = Long.valueOf(response.getTimestamp());
                        mDatabind.viewWaterMask.updateTime(TimeUtils.millis2Date(time * 1000));
                        mDatabind.viewWaterMask1.updateTime(TimeUtils.millis2Date(time * 1000));
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        // 处理请求失败的情况
                        throwable.printStackTrace();
                        mDatabind.viewWaterMask.updateTime(null);
                        mDatabind.viewWaterMask1.updateTime(null);
                        LogExtKt.logE("校准时间 异常" + throwable.getMessage(), TAG);
                    }
                });
    }


    @Override
    public void onRequestSuccess() {

        //拿到地址信息，做对比
        mViewModel.getAddressManager().observe(this, new Observer<AddressEntity>() {
            @Override
            public void onChanged(AddressEntity addressEntity) {
                double nowLatitude = currentLatitude;
                double nowLongitude = currentLongitude;
                LogUtils.e("地址对比之前的经纬度->" + "当前经度纬度是:" + nowLatitude + " ; " + nowLongitude);

                double targetLatitude, targetLongitude;
                double distance;

                for (AddressListEntity list : addressEntity.getList()) {
                    targetLatitude = Double.parseDouble(list.getLat());
                    targetLongitude = Double.parseDouble(list.getLnt());

                    distance = DistanceUtil.getDistance(new LatLng(nowLatitude, nowLongitude), new LatLng(targetLatitude, targetLongitude));

                    LogUtils.e("地址对比出来的距离->" + "当前地址是:" + list.getAddress() + " ; 计算出来的距离是 ->" + distance);

                    if (distance < 500) {
                        LogUtils.e("当前距离小于 300米了 具体位置是" + list.getAddress() + " ；要是不信，看看计算出来的值吧 " + distance);
                        // 如果距离小于300米，停止循环
                        currentLatitude = targetLatitude;
                        currentLongitude = targetLongitude;
                        currentAddress = list.getAddress();
                        //重新设置下地址
                        mDatabind.viewWaterMask.getTvAddress().setText(list.getAddress());
                        mDatabind.viewWaterMask1.getTvAddress().setText(list.getAddress());
                        break;
                    }
                }
            }
        });
    }

    /**
     * 百度的定位回调
     */
    private BDAbstractLocationListener mListener = new BDAbstractLocationListener() {

        /**
         * 定位请求回调函数
         * @param location 定位结果
         */
        @Override
        public void onReceiveLocation(BDLocation location) {
            logText("onReceiveLocation 百度定位完成了 当前位置" + location.getAddrStr());
            LogUtils.e("onReceiveLocation百度定位完成了`--");
            if (null != location && location.getLocType() != BDLocation.TypeServerError) {
                locService.stop();
                if (isLocationOpen(WatermarkCameraActivity.this)) {
                    Constant.LATITUDE = location.getLatitude();
                    Constant.LONGITUDE = location.getLongitude();

                    currentLatitude = location.getLatitude();
                    currentLongitude = location.getLongitude();
                    currentAddress = location.getAddrStr();
                    //重新设置下地址
                    mDatabind.viewWaterMask.getTvAddress().setText(currentAddress);
                    mDatabind.viewWaterMask1.getTvAddress().setText(currentAddress);
                    mViewModel.requestAddressAll();
                } else {
                    mDatabind.viewWaterMask.getTvAddress().setText("请开启手机的定位服务。");
                    mDatabind.viewWaterMask1.getTvAddress().setText("请开启手机的定位服务。");
                }
            }
        }

        @Override
        public void onConnectHotSpotMessage(String s, int i) {
            super.onConnectHotSpotMessage(s, i);
            LogUtils.e("获取地址定位onConnectHotSpotMessage--" + s + " ; code =" + i);
            logText("onConnectHotSpotMessage =" + s + " ; code 码 = " + i);
        }

        /**
         * 回调定位诊断信息，开发者可以根据相关信息解决定位遇到的一些问题
         * @param locType 当前定位类型
         * @param diagnosticType 诊断类型（1~9）
         * @param diagnosticMessage 具体的诊断信息释义
         */
        @Override
        public void onLocDiagnosticMessage(int locType, int diagnosticType, String diagnosticMessage) {
            super.onLocDiagnosticMessage(locType, diagnosticType, diagnosticMessage);
            LogUtils.e("获取地址定位onLocDiagnosticMessage--" + diagnosticMessage + " ; code =" + diagnosticType + "  定位类型 ->" + locType);
            logText("onLocDiagnosticMessage =" + diagnosticMessage + " ; code 码 = " + diagnosticType + " ; 定位类型= " + locType);
        }
    };

    private StringBuilder stringBuilder = new StringBuilder();

    private void logText(String text) {
        stringBuilder.append(text).append("\n");
        if (BuildConfig.DEBUG) {
//            mDatabind.tvTips.setText(stringBuilder.toString());
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (disposablePhoto != null && !disposablePhoto.isDisposed()) {
            disposablePhoto.dispose();
        }
        if (disposableTimer != null && !disposableTimer.isDisposed()) {
            disposableTimer.dispose();
            disposableTimer = null;
        }
        if (null != locService) {
            locService.unregisterListener(mListener); //注销掉监听
            locService.disableAssistantLocation();
            locService.stop();
        }
    }

    /**
     * 上传图片的操作
     * message_type 区分是图片还是视频
     */
    private void uploadMedia(int message_type, String waterFile, String original, String thumb) {

        RxHttp.get(NetUrl.CHECK_CLOCK_ADDRESS)
                .add("lnt", "" + currentLongitude)
                .add("lat", "" + currentLatitude)
                .asResponse(CheckClockInEntity.class)
                .timeout(3, TimeUnit.SECONDS)  //设置总超时时间为5s，在toObservableXxx方法后调用
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<CheckClockInEntity>() {
                    @Override
                    public void accept(CheckClockInEntity response) throws Exception {
                        if (!TextUtils.isEmpty(response.getMessage())) {
                            CommonUtils.showGeneralDialogNoCancel(WatermarkCameraActivity.this, "温馨提示", response.getMessage(), "知道了", null);
                            return;
                        }
                        //1打卡 2领班打卡 3日常
                        int actType = 1;
                        if (mAdapter.getText().equals("日常")) {
                            actType = 3;
                        } else if (mAdapter.getText().equals("领班打卡")) {
                            actType = 2;
                        }
                        ServerReporter.getInstance().reportToServer(actType, message_type, currentLatitude, currentLongitude, currentAddress, waterFile, original, thumb, null, null, takePhotoMills);
                        new XPopup.Builder(WatermarkCameraActivity.this)
                                .asCustom(new CustomClockInDialog(WatermarkCameraActivity.this))
                                .show();
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                    }
                });
    }


    @Override
    public void onBackPressed() {
        // 禁止用户返回
    }


    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            // 禁止用户点击虚拟按钮返回
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
}